from dataclasses import dataclass
import psycopg2
from django.db.models import CharField, F
from django.db.models.functions import Cast
import json
from administrators.views.token_check import verify_token  # 注意，这个是从管理应用引入的
from django.views.decorators.http import require_http_methods
from utils.enums import SCE
from utils.result import R
from django.db import IntegrityError
from datetime import date
from utils.tools import ParamCheck
# ---------------------------------------------------------------------
from inventory.models import Handle, HandleGroup


@dataclass  # 停用和启用 的请求参数
class Type1:
    id: int


# 处理方分组的停用和启用
@verify_token()
@require_http_methods(['POST'])
def handle_group_deactivation_and_activation(request, user_id: str):
    data = Type1(id=ParamCheck.int(json.loads(request.body)['id']))
    try:
        obj = HandleGroup.objects.get(id=data.id)
        use = not obj.enable  # 希望调整为的状态
        if use:  # 如果希望启用该分组
            obj.enable = True
            obj.save()  # 启用分组
            temp1 = Handle.objects.filter(handle_group=data.id)
            for i in temp1:
                i.enable = True
            Handle.objects.bulk_update(temp1, fields=['enable'])  # 启用该分组下的所有物料
            return R.success('处理方分组已经启用').data()
        else:  # 如果希望关闭该分组
            # 检查该分组下的未关闭的物料是否均满足关闭条件
            temp2 = Handle.objects.filter(handle_group_id=data.id, enable=True)
            obj.enable = False  # 停用分组
            obj.save()
            for i in temp2:
                i.enable = False
            Handle.objects.bulk_update(temp2, fields=['enable'])  # 停用该处理方分组下的所有处理方
            return R.success('处理方分组已经停用').data()

    except HandleGroup.DoesNotExist:
        return R.error(SCE.no_enum, '要操作的处理方分组不存在').data()
    except KeyError:  # 为dataclass赋值错误
        return R.error(SCE.ParamError).data()


# 处理方的停用和启用
@verify_token()
@require_http_methods(['POST'])
def handle_deactivation_and_activation(request, user_id: str):
    data = Type1(id=ParamCheck.int(json.loads(request.body)['id']))
    # 如果该处理方所属分组处于关闭状态，那么其下的处理方状态不得变更
    try:
        obj = Handle.objects.get(id=data.id)
        temp1 = obj.handle_group
        if not temp1.enable:
            return R.error(SCE.no_enum, '处理方所属分组处于关闭状态，状态不可更改').data()

        use = not obj.enable  # 希望调整为的状态

        if use:  # 如果希望启用该处理方
            obj.enable = True
            obj.save()

            return R.success('处理方已经启用').data()
        else:  # 如果希望关闭该处理方
            obj.enable = False
            obj.save()
            return R.success('处理方已经停用').data()

    except Handle.DoesNotExist:
        return R.error(SCE.no_enum, '要操作的处理方不存在').data()
    except KeyError:  # 为dataclass赋值错误
        return R.error(SCE.no_enum, '请求参数错误').data()


# 处理方的增删改查
@verify_token()
@require_http_methods(['POST'])
def handle_crud(request, user_id: int):
    data = json.loads(request.body)
    match data['mode']:
        case 'create':
            name: str = data['create']['handle_name']
            mnemonic: str = data['create']['mnemonic']
            handle_group_id: int = data['create']['handle_group_id']

            try:
                Handle.objects.create(mnemonic=mnemonic,
                                      operate_date=date.today(),
                                      operator_id=user_id,
                                      enable=True,
                                      name=name,
                                      handle_group_id=handle_group_id),
                return R.success(f"新增处理方 {name} 成功").data()

            except IntegrityError as e:
                if isinstance(e.__cause__, psycopg2.errors.UniqueViolation):
                    if 'mnemonic' in str(e):
                        return R.error(SCE.no_enum, '要添加的处理方中助记码重复').data()
                    if 'handle' in str(e):
                        return R.error(SCE.no_enum, '要添加的处理方中处理方名称重复').data()
            except HandleGroup.DoesNotExist:
                return R.error(SCE.no_enum, '处理方所属分组不存在').data()

        case 'delete':
            delete_id: int = data['delete']['id']
            try:
                Handle.objects.get(id=delete_id).delete()
                return R.success(f"处理方删除成功").data()
            except Handle.DoesNotExist:
                return R.error(SCE.no_enum, '要删除的处理方不存在').data()
            except IntegrityError:
                return R.error(SCE.no_enum, '该处理方尚有创建的记录未删除，请先删除').data()

        case 'update':
            handle_name: str = data['update']['handle_name']
            mnemonic: str = data['update']['mnemonic']
            handle_id: int = data['update']['handle_id']
            handle_group_id: int = data['update']['handle_group_id']

            try:
                handle_obj = Handle.objects.get(id=handle_id)
                handle_obj.name = handle_name
                handle_obj.mnemonic = mnemonic
                handle_obj.operator_id = user_id
                handle_obj.creation_date = date.today()
                handle_obj.handle_group_id = handle_group_id
                handle_obj.save()
                return R.success(f"处理方 {handle_name} 修改成功").data()
            except Handle.DoesNotExist:
                return R.error(SCE.no_enum, '要修改的处理方不存在').data()
            except IntegrityError as e:
                if 'handlegroup' in str(e):
                    return R.error(SCE.no_enum, '所属的组不存在').data()

        case 'read':
            handle_id = ParamCheck.int(data['read']['handle_id'])
            result = (Handle.objects
                      .filter(id=handle_id)
                      .annotate(operator_name=F('operator__username', handle_group_name=F('group__name')))
                      .values('id', 'name', 'mnemonic', 'operator_name', 'enable', 'handle_group_name', 'handle_group_id',
                              operate_date_=Cast('operate_date', CharField())))
            return R.success('处理方读取成功').data({result: list(result)})
        case _:
            return R.error(SCE.ParamError).data()


# 处理方分组的增删改查
@verify_token()
@require_http_methods(['POST'])
def handle_group_crud(request, user_id: int):
    data = json.loads(request.body)
    match data['mode']:
        case 'create':
            name: str = data['create']['name']
            mnemonic: str = data['create']['mnemonic']
            try:
                HandleGroup.objects.create(name=name,
                                           mnemonic=mnemonic,
                                           operate_date=date.today(),
                                           operator_id=user_id,
                                           enable=True)
                return R.success('添加分组成功').data()
            except IntegrityError as e:
                if 'name' in str(e):
                    return R.error(SCE.no_enum, '分组名称重复').data()
                if 'mnemonic' in str(e):
                    return R.error(SCE.no_enum, '分组助记码重复').data()

        case 'delete':
            handle_group_id: int = data['delete']['handle_group_id']
            try:
                HandleGroup.objects.get(id=handle_group_id).delete()
                return R.success('删除分组成功').data()
            except HandleGroup.DoesNotExist:
                return R.error(SCE.no_enum, '要删除的分组不存在').data()
            except IntegrityError:
                return R.error(SCE.no_enum, '要删除的分组中尚有处理方未删除').data()

        case 'update':
            handle_group_id: int = data['update']['handle_group_id']
            name: str = data['update']['name']
            mnemonic: str = data['update']['mnemonic']
            try:
                group_obj = HandleGroup.objects.get(id=handle_group_id)
                group_obj.name = name
                group_obj.mnemonic = mnemonic
                group_obj.operator_id = user_id
                group_obj.operate_date = date.today()
                group_obj.save()
                return R.success('分组修改完成').data()
            except HandleGroup.DoesNotExist:
                return R.error(SCE.no_enum, '要修改的分组不存在').data()

        case 'read':
            handle_group_id: str = data['read']['handle_group_id']
            result = (HandleGroup.objects
                      .filter(id=handle_group_id)
                      .annotate(operator_name=F('operator__username'))
                      .values('id', 'name', 'mnemonic', 'operator_name', 'enable',
                              operate_date_=Cast('operate_date', CharField())))
            return R.success('物料读取成功').data({result: list(result)})

        case _:
            return R.error(SCE.ParamError).data()


# 处理方模糊搜索
@verify_token()
@require_http_methods(['POST'])
def handle_fuzzy_search(request, user_id: int):
    data = json.loads(request.body)
    # 以指定分组进行搜索
    handle_group_id = ParamCheck.int(data['handle_group_id'], force=False)
    # 以名称和助记码进行搜索
    name = ParamCheck.str(data['handle_name'], length=(0, 100), force=False)
    mnemonic = ParamCheck.str(data['mnemonic'], length=(0, 100), force=False)
    # 以是否启用进行搜索
    enable = ParamCheck.str(data['enable'])
    start: int = ParamCheck.int(data['start'])
    stop: int = ParamCheck.int(data['stop'])

    result = Handle.objects

    if name is not None:
        result = result.filter(name__contains=name)
    if mnemonic is not None:
        result = result.filter(mnemonic__contains=mnemonic)
    if enable == 'enable':
        result = result.filter(enable=True)
    if enable == 'not_enable':
        result = result.filter(enable=False)
    if handle_group_id is not None:
        result = result.filter(handle_group__id=handle_group_id)

    result = (result
              .annotate(operator_name=F('operator__username'), handle_group_name=F('handle_group__name'))
              .values('id', 'name', 'mnemonic', 'operator_name', 'enable', 'handle_group_name', 'handle_group_id',
                      operate_date_=Cast('operate_date', CharField())))
    # 返回条数，在不分页的情况下
    total: int = result.count()
    result = result[start: stop]
    return R.success('搜索成功').data({'result': list(result), 'total': total})


# 处理方分组模糊搜索
@verify_token()
@require_http_methods(['POST'])
def handle_group_fuzzy_search(request, user_id: int):
    data = json.loads(request.body)
    # 以名称和助记码进行搜索
    name = ParamCheck.str(data['name'], length=(0, 100), force=False)
    mnemonic = ParamCheck.str(data['mnemonic'], length=(0, 100), force=False)
    # 以是否启用进行搜索
    enable = ParamCheck.str(data['enable'])

    start: int = ParamCheck.int(data['start'])
    stop: int = ParamCheck.int(data['stop'])

    result = HandleGroup.objects

    if name is not None:
        result = result.filter(name__contains=name)
    if mnemonic is not None:
        result = result.filter(mnemonic__contains=mnemonic)
    if enable == 'enable':
        result = result.filter(enable=True)
    if enable == 'not_enable':
        result = result.filter(enable=False)

    result = (result
              .annotate(operator_name=F('operator__username'))
              .values('id', 'name', 'mnemonic', 'operator_name', 'enable',
                      operate_date_=Cast('operate_date', CharField())))
    # 返回条数，在不分页的情况下
    total: int = result.count()
    result = result[start: stop]
    return R.success('搜索成功').data({'result': list(result), 'total': total})
